// file: listener.c
//
// LCM example program.
//
// compile with:
//  $ gcc -o listener listener.c -llcm
//
// If using GNU/Linux, you can also use pkg-config:
//  $ gcc -o listener listener.c `pkg-config --cflags --libs lcm`

#include <stdio.h>
#include <stdlib.h>
#include <inttypes.h>
#include <lcm/lcm.h>
#include <string.h>

#include "example_t.h"

//globals for reconstructing messages from packets
int packet_count = 0;
char* message_buffer_id = NULL;   //storage for the current message id
char* message_buffer = NULL;      //storage for the current message
int* packet_counter = NULL;

void write_file (char buffer[], int32_t length, char* filename)
{
	//create filename for output
	char* videofilename = (char*)malloc(sizeof(char)*128);
	strcpy(videofilename,"tmpvid/");
	strcat(videofilename,filename);

	//open file for write
	FILE * ofp;
	ofp = fopen (videofilename, "wb");
	if (ofp==NULL) {fputs ("File error",stderr); exit (1);}

	//write to file
	fwrite (buffer, 1, length, ofp);
	fclose (ofp);
}

static void my_handler 
	(const lcm_recv_buf_t *rbuf, const char * channel,const example_t * msg, void * user)
{
	int i, success;
	int waiting;
	char* filename;

	/*
	printf ("Received message on channel \"%s\":\n", channel); 
	printf ("  Message id  		= %s\n", msg->message_id);
	printf ("  Bytes in Message	= %d\n", msg->bytes_in_message);
	printf ("  Packet id  		= %d\n", msg->packet_id);
	printf ("  Number of packets  	= %d\n", msg->number_of_packets);
	printf ("  Max Bytes in Packet	= %d\n", msg->max_bytes_in_packet);
	printf ("  Bytes in Packet	= %d\n", msg->bytes_in_packet);;
	*/
	
	//display recieved packet data to screen
	/*
	printf ("  Data : ");
	for (i = 0; i<msg->bytes_in_packet; i++)
	{
		printf ("%c", msg->frame_data[i]); 	
	}
	printf ("\n");
	*/

	//new message detected
	if (message_buffer_id == NULL || strcmp(message_buffer_id,msg->message_id))
	{
		//free current message buffer id if one exists then create a new one
		if (message_buffer_id != NULL)
		{	
			free (message_buffer_id);
			printf("Incomplete message dropped\n");
		}
		message_buffer_id = (char*)malloc(sizeof(char)*(strlen(msg->message_id)+1)); 
		
		//free current message buffer if one exists then create a new one
		if (message_buffer != NULL)
			free (message_buffer);
		message_buffer = (char*)malloc(sizeof(char)*(msg->max_bytes_in_packet*msg->number_of_packets +1));

		//free current packet counter if one exists then create a new one
		if (packet_counter != NULL)
			free (packet_counter);
		packet_counter = (int*)malloc(sizeof(int)*(msg->number_of_packets));
		for (i = 0; i <msg->number_of_packets; i++)
		{
			*(packet_counter + i) = 0;
		}

		printf("New message detected.\n");
		strcpy(message_buffer_id,msg->message_id);
	}
	
	//store packet in appropriate part of message buffer
	for (i=0; i < msg->bytes_in_packet; i++)
	{
		*(message_buffer+(msg->packet_id-1) * msg->max_bytes_in_packet + i) = *(msg->frame_data +i);
	}

	//set packet counter flag for this packet
	*(packet_counter + msg->packet_id -1) = 1;
	printf("Packet %d of %d recieved\n",msg->packet_id,msg->number_of_packets);

	//check if still waiting for packets in current message
	waiting = 0;
	for (i = 0; i < msg->number_of_packets; i++)
	{
		

		if (*(packet_counter + i) == 0) waiting = 1;
	}
	if (!waiting)
	{
		printf("All packets from message %s recieved\n",message_buffer_id);
		
		//generate output filename
		filename = (char*)malloc(sizeof(char)*256); //hardcoded filepath length !!	
		strcpy(filename,msg->message_id);
		//strcat(filename,"%d.ppm"); //for images

		//write the recieved data to file
		write_file(message_buffer, msg->bytes_in_message, filename);

		//decode video into images
		success = decode_video(filename);
		
		free(filename);
		filename=NULL;

		//free message resources
		free(message_buffer_id);	
		message_buffer_id = NULL;
		free(message_buffer);
		message_buffer = NULL;
		free(packet_counter);
		packet_counter = NULL;

	}

}

int main (int argc, char ** argv)
{
	 // must be called before using avcodec lib 
    	avcodec_init();

    	// register all the codecs 
    	avcodec_register_all();
	
    	lcm_t * lcm;

    	lcm = lcm_create ("udpm://");
    	if (!lcm)
        return 1;

    	example_t_subscription_t * sub =
        	example_t_subscribe (lcm, "EXAMPLE", &my_handler, NULL);

    	while (1)
	{
        	lcm_handle (lcm);
	}

    	example_t_unsubscribe (lcm, sub);
    	lcm_destroy (lcm);
    	return 0;
}






